/*
 * @Author: 王雁鹏
 * @Date: 2023-06-25 20:19:43
 * @LastEditTime: 2023-07-31 14:11:26
 * @LastEditors: Please set LastEditors
 * @Description: 
 * @FilePath: \expressf:\web-vue\bs-nodejs-background-code\routes\pay\service.js
 * -------------------------------------
 */
/* 
 * Created by Asnull.
 * Website:https://lipux.cn/
 */

const WxPay = require('wechatpay-node-v3');
const fs = require('fs');
const request = require('superagent');
const express = require('express');
var req = require("../../utils/router");
const db = require("../../mysql/index.js");
const { generateUUID, randomNumber, createToken, createTime } = require("../../utils/func.js")
let { router, GetRouter, PostRouter } = req
class timeFnClass {
    constructor() {
        this.area = {}
    }
    timeout(openid, id, time) {
        let timeNum = (time * 1000 * 60) || (1000 * 60 * 30)
        this.area[openid] = setTimeout(() => {
            let condition = { status: "3" }
            let params = {
                db: "wh_shop",
                id,
                condition
            }
            db.setData(params, () => {
                delete this.area[openid]
            })
            db.setData({
                db: "wh_order",
                query: `o_user='${openid}' AND o_status='1'`,
                condition: { status: "4" }
            })
        }, timeNum)
        return time
    }
    close(openid, time) {
        let timeNum = (time * 1000 * 60) || (1000 * 60 * 30)
        setTimeout(() => {
            db.setData({
                db: "wh_order",
                query: `o_user='${openid}' AND o_status='1'`,
                condition: { status: "4" }
            })
        }, timeNum)
        return time
    }
    delTimeout(openid) {
        if (this.area[openid]) {
            clearTimeout(this.area[openid])
            delete this.area[openid]
        }
    }
}
let timeFn = new timeFnClass()
// 创建服务器实例
const app = express();
let setOrderList = (list, code, success) => {
    let [params, ...data] = list
    let { openid, produce_id, num } = params
    let condition = { produce_id, code, num }
    db.setData({
        db: "wh_order_list",
        condition
    }, (rows, fields) => {
        if (data && data.length > 0) {
            setOrderList(data, code, success)
        } else {
            let obj = {
                code: db.EQ({ db: "wh_shop", select: { code: openid } }),
            }
            let select = db.Params(obj)
            db.select({
                db: "wh_shop",
                select
            }, (data) => {
                if (data.list.length > 0) {
                    let id = data.list[0].id
                    let condition = { status: "1" }
                    db.setData({
                        db: "wh_shop",
                        id,
                        condition
                    }, () => {
                        let time = 30
                        timeFn.timeout(openid, id, time)
                        if (success) {
                            success(rows, time)
                        }
                    })
                } else {
                    let time = 30
                    timeFn.close(openid, time)
                    success(rows, time)
                }
            })
        }
    })
}
let setOrder = ({
    list = [],
    openid,
    code,
    type = "1",
    status = "2",
    addressId, success
}) => {
    const time = createTime()
    let condition = { user_id: openid, address: addressId, status, code, time, type }
    db.setData({
        db: 'wh_order',
        condition
    }, (rows) => {
        console.log(list, "listlistlist")
        if (list.length > 0) {
            setOrderList(list, code, success)
        } else {
            if (success) {
                success(rows)
            }
        }
    })
}
let setScore = ({ data, priceFn, success }) => {
    let openid = data.openid;
    let price = data.price
    let obj = {
        openid: db.EQ({
            db: "wh_users",
            select: {
                openid
            }
        }),
    }
    let select = db.Params(obj)
    db.select({
        db: 'wh_users',
        select
    }, (rows) => {
        let { score, id } = rows.list[0]
        let num = priceFn(score, price)
        db.setData({
            db: 'wh_users',
            id,
            condition: {
                openid,
                score: num.toFixed(2)
            }
        }, (rows, fields) => {
            return success(rows, score, price)
        })
    })
}
// 创建支付实例
const pay = new WxPay({
    appid: 'wxf8b267cff4c3bd83',
    mchid: '1647727052',
    publicKey: fs.readFileSync(`${__dirname}/apiclient_cert.pem`), // 公钥
    privateKey: fs.readFileSync(`${__dirname}/apiclient_key.pem`), // 秘钥
});

// 定义一个获取支付参数路由（get请求）
// 拿到支付所需参数
new GetRouter().send('/pay', (res, data) => {
    console.log(data, "datadatadata")
    // 接收前端传过来的openid
    let openid = data.openid;
    let addressId = data.addressId
    if (!addressId) {
        res.send({ code: 100, data: {}, msg: "订单缺少备注信息" })
    }
    let list = JSON.parse(data.list) || []
    if (list.length == 0) {
        return res.send({ code: 101, msg: "请选择要支付的商品！" })
    }
    let id = data.id
    let price = list.reduce((current, item) => {
        current += (item.price * item.num)
        return current
    }, 0)
    data.price = price
    price = price * 100
    let code = randomNumber()
    // if (addPrice !== price) {
    //     res.send({ code: "error", data: [], message: "订单价格不一致" })
    // }
    const params = {
        description: 'Asnull的支付测试', // 订单描述
        out_trade_no: code, // 订单号，一般每次发起支付都要不一样，可使用随机数生成
        notify_url: 'https://wypxxyy.cn/tiequan/notify_url',
        amount: {
            total: price, // 支付金额，单位为分
        },
        payer: {
            openid: openid, // 微信小程序用户的openid，一般需要前端发送过来
        },
        scene_info: {
            payer_client_ip: 'ip', // 支付者ip，这个不用理会也没有问题
        },
    };

    const fn = async () => {
        let result = await pay.transactions_jsapi(params);
        let arr = list.map((item) => {
            return { ...item, openid }
        })
        setOrder({
            list: arr, openid, addressId, code, status: "1", success: (rows, time) => {
                let date = createTime({ minutes: time })
                console.log({ ...result, date }, "{ ...result, dd: { date, date1, date2 } }")
                res.send({ ...result, date });
            }
        })

    }
    let result = fn()
    // 将结果响应给微信小程序前端
});

new PostRouter().send('/scorePay', (res, data) => {
    let openid = data.openid
    let list = JSON.parse(data.list) || []
    // 接收前端传过来的openid
    let arr = list.map((item) => {
        return { ...item, openid }
    })
    data.price = list[0].price
    let code = randomNumber()
    setOrder({ list: arr, openid, code, type: "2" })
    setScore({
        data,
        priceFn: (score, price) => {
            let num = Number(score) - Number(price)
            if (num < 0) {
                res.send({ code: "100", data: {}, msg: "积分不足" });
                return 0
            }
            let condition = { openid: openid, status: "2", record: Number(price) }
            db.setData({
                db: "wh_record",
                condition
            }, (rows, fields) => {
                return num
            })
            return num
        },
        success: (rows, score, price) => {
            res.send({ code: "200", data: {}, msg: "积分已扣除" });
        }
    })
    // 将结果响应给微信小程序前端
});


// 回调路由
new PostRouter().send('/notify_url', async (res, data) => {
    // 申请的APIv3
    let key = '45c18fdfdgd45f5bc5321201dfdf453f';
    let { ciphertext, associated_data, nonce } = data.resource;
    // 解密回调信息
    const result = pay.decipher_gcm(ciphertext, associated_data, nonce, key);
    if (result.trade_state == 'SUCCESS') {
        // 拿到订单号
        let { out_trade_no, payer: { openid }, amount: { total } } = result;
        let params = {
            openid,
            price: total / 100
        }
        let obj = {
            code: db.EQ({ db: "wh_shop", select: { code: openid } }),
        }
        let select = db.Params(obj)
        timeFn.delTimeout(openid)
        db.delete({
            db: "wh_shop",
            select
        })
        db.delete({
            db: "wh_shop_list",
            select
        })
        // 支付成功之后需要进行的业务逻辑
        setScore({
            data: params,
            priceFn: (score, price) => {
                let num = Number(score) + Number(price)
                return num
            },
            success: (rows, score, price) => {
                res.send(result);
                let num = Number(score) + Number(price)
                let condition = { openid: openid, record: Number(price) }
                let obj = {
                    code: db.EQ({
                        db: "wh_order",
                        select: {
                            code: out_trade_no
                        }
                    }),
                }
                let select = db.Params(obj)
                console.log(select)
                db.select({
                    db: 'wh_order',
                    select
                }, (rows) => {
                    let { score, id } = rows.list[0]
                    db.setData({
                        db: 'wh_order',
                        id,
                        condition: {
                            status: "2"
                        }
                    }, (rows, fields) => {
                        return rows
                    })
                })
                db.setData({
                    db: "wh_record",
                    condition
                }, (rows, fields) => {
                    return num
                })
                return
            }
        })
    }
})


module.exports = router
